package framework;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

public class State {
	private static int numberOfPins = 3;
	public static Map<String, double[]> allStates = new HashMap<String, double[]>();

	public static void generateAllStates() {
		allStates.clear();
		for (int i = 0; i < numberOfPins; i++) { // All pins for A
			for (int j = 0; j < numberOfPins; j++) { // All pins for B
				if (i == j) {
					allStates.put(String.format("%s%s%s%s", i, j, 1, 2), new double[] { i, j, 1, 2,
							0 });
					allStates.put(String.format("%s%s%s%s", i, j, 2, 1), new double[] { i, j, 2, 1,
							0 });
				} else {
					allStates.put(String.format("%s%s%s%s", i, j, 1, 1), new double[] { i, j, 1, 1,
							0 });
				}
			}
		}
		System.out.println("Generated: " + allStates.size() + " states");
	}

	public static double getValue(double[] state) {
		if (state[0] == 2 && state[1] == 2 && state[2] == 1 && state[3] == 2) {
			return 100;
		}
		if (state[0] == state[1] && state[2] > state[3]) {
			return -10;
		}
		return -1;
	}

	public static ArrayList<String> getPossibleTransitions(double[] state) {
		ArrayList<String> list = new ArrayList<String>();
		// Absorbing states, have no more transitions.
		// End state
		if (state[0] == 2 && state[1] == 2 && state[2] == 1 && state[3] == 2) {
			return list;
		}

		int posA = (int) state[0];
		int posB = (int) state[1];
		int stackA = (int) state[2];
		int stackB = (int) state[3];
		// If A is below B
		if (stackA == 1 && stackB == 2 && posA == posB) {
			for (int i = 0; i < numberOfPins; i++) {
				if (i != posB) {
					list.add(String.format("%s%s%s%s", posA, i, 1, 1));
				}
			}
		}
		// If B is below A
		else if (stackB == 1 && stackA == 2 && posA == posB) {
			for (int i = 0; i < numberOfPins; i++) {
				if (i != posA) {
					list.add(String.format("%s%s%s%s", i, posB, 1, 1));
				}
			}
			// They aren't on top of each other
		} else {
			// Possible actions for A
			for (int i = 0; i < numberOfPins; i++) {
				if (i != posA) {
					if (i == posB) {
						// Putting it on B
						list.add(String.format("%s%s%s%s", i, posB, 2, 1));
					} else {
						// Putting it on an empty stack
						list.add(String.format("%s%s%s%s", i, posB, 1, 1));
					}
				}
			}
			// Possible actions for B
			for (int i = 0; i < numberOfPins; i++) {
				if (i != posB) {
					if (i == posA) {
						// Putting it on A
						list.add(String.format("%s%s%s%s", posA, i, 1, 2));
					} else {
						// Putting it on an empty stack
						list.add(String.format("%s%s%s%s", posA, i, 1, 1));
					}
				}
			}
		}
		return list;
	}

	public static String toString(double[] state) {
		return String.format("%s%s%s%s", (int) state[0], (int) state[1], (int) state[2],
				(int) state[3]);
	}

	public static String toVisualString(double[] state, boolean printUtil) {
		StringBuilder builder = new StringBuilder();

		builder.append("| | |\n");
		if (state[2] == 2) {
			if (state[0] == 0) {
				builder.append("A | |\n");
			}
			if (state[0] == 1) {
				builder.append("| A |\n");
			}
			if (state[0] == 2) {
				builder.append("| | A\n");
			}
		}
		if (state[3] == 2) {
			if (state[1] == 0) {
				builder.append("B | |\n");
			}
			if (state[1] == 1) {
				builder.append("| B |\n");
			}
			if (state[1] == 2) {
				builder.append("| | B\n");
			}
		}
		String[] bottom = { "|", "|", "|" };
		if (state[2] == 1) {
			bottom[(int) state[0]] = "A";
		}
		if (state[3] == 1) {
			bottom[(int) state[1]] = "B";
		}
		builder.append(bottom[0] + " " + bottom[1] + " " + bottom[2] + "\n");
		builder.append("-----\n");
		if (printUtil) {
			builder.append("Utility: " + state[4] + "\n");
		}
		return builder.toString();
	}

	public static String visualStates() {
		StringBuilder builder = new StringBuilder();

		Collection<double[]> s = allStates.values();
		Iterator<double[]> iterator = s.iterator();

		while (iterator.hasNext()) {
			builder.append(State.toVisualString(iterator.next(),false));
			builder.append("\n");
		}

		return builder.toString();
	}
}
